module ysyx_050369_reg_sb ( 
    input        clk,
    input        rst,
    input [127:0]i_cache_data,
    //reg_data
    input [4:0]  i_id_rs1,
    input [4:0]  i_id_rs2,
        //form ex
    input        i_ex_wen,
    input [4:0]  i_ex_waddr,
    input [63:0] i_ex_wdata,
    input        i_ex_mem2reg,
    input        i_ex_memwen,
    input [31:0] i_ex_memraddr,
    input [7 :0] i_ex_memmask,
    input        i_as0_wen,
    input [4:0]  i_as0_waddr,
    input [63:0] i_as0_wdata,
    input        i_as0_memren,
    input [31:0] i_as0_memraddr,
    input [7 :0] i_as0_memmask,
    input        i_as0_memwen,
    input        i_as1_wen,
    input [4:0]  i_as1_waddr,
    input [63:0] i_as1_wdata,
    input        i_as1_memren,
    input [63:0] i_as1_memrdata,
    input [31:0] i_as1_memraddr,
        //form wb
    input [63:0] i_rd_1,
    input [63:0] i_rd_2, 
        //to ex
    output[63:0] o_rd1,
    output[63:0] o_rd2,
    output       reg_stop
);
    wire [2:0]rs1_hit;
    wire [2:0]rs1_en;
    wire [63:0] cache_buffer_temp_1;
    wire [63:0] cache_buffer_temp_0;
    wire [1:0]addr_hit;
    wire [1:0]addr_en;
    reg [63:0] cache_data_0;
    reg [63:0] cache_data_1;
    wire [3:0] offset_0;
    wire [7:0] mask_0;
    wire [3:0] offset_1;
    wire [7:0] mask_1;
    reg [127:0] cache_buffer;
    reg [28:0]  cache_info;
    always @(posedge clk ) begin
        if (rst) begin
            cache_buffer <= 'b0;
            cache_info <= 'b0;
        end
        else begin
            if ((addr_hit[0] && i_ex_memwen) || (addr_hit[1] && i_as0_memwen)) begin
                cache_info  <= 'b0;
            end
            else if (((i_ex_memraddr [31:4] ==  i_as1_memraddr[27:0]) && i_ex_memwen) || 
                     ((i_as0_memraddr[31:4] ==  i_as1_memraddr[27:0]) && i_as0_memwen)) begin
                cache_info  <= 'b0;
            end
            else if (i_as1_memren) begin
                cache_buffer <= i_cache_data;
                cache_info <= {1'b1,i_as1_memraddr[31:4]};
            end
            
        end 
    end
    assign addr_hit[0]=  (i_ex_memraddr[31:4] ==  cache_info[27:0])&& cache_info[28];
    assign addr_hit[1]=  (i_as0_memraddr[31:4] == cache_info[27:0])&& cache_info[28];
    assign addr_en [0]= addr_hit[0] && i_ex_mem2reg;
    assign addr_en [1]= addr_hit[1] && i_as0_memren;
    assign  cache_buffer_temp_0  = {64'b0,cache_buffer}[({1'b0,i_ex_memraddr[3:0],3'b0})+:64];
    assign  cache_buffer_temp_1  = {64'b0,cache_buffer}[({1'b0,i_as0_memraddr[3:0],3'b0})+:64];
    // assign cache_buffer_temp_0   = {cache_buffer>>{i_ex_memraddr[3:0],3'b0}};
    // assign cache_buffer_temp_1   = {cache_buffer>>{i_as0_memraddr[3:0],3'b0}};
    always @(*) begin
        case (i_ex_memmask)
            8'h01 : cache_data_0 = {{56{cache_buffer_temp_0[ 7]}},cache_buffer_temp_0[ 7:0]};
            8'h03 : cache_data_0 = {{48{cache_buffer_temp_0[15]}},cache_buffer_temp_0[15:0]};
            8'h07 : cache_data_0 = {{32{cache_buffer_temp_0[31]}},cache_buffer_temp_0[31:0]};
            8'h0f : cache_data_0 =                                cache_buffer_temp_0[63:0] ;
            8'h81 : cache_data_0 = {56'b0                        ,cache_buffer_temp_0[ 7:0]};
            8'h83 : cache_data_0 = {48'b0                        ,cache_buffer_temp_0[15:0]};
            8'h87 : cache_data_0 = {32'b0                        ,cache_buffer_temp_0[31:0]};
            default: cache_data_0 = 'b0;
        endcase
    end
    always @(*) begin
        case (i_as0_memmask)
            8'h01 : cache_data_1 = {{56{cache_buffer_temp_1[ 7]}},cache_buffer_temp_1[ 7:0]};
            8'h03 : cache_data_1 = {{48{cache_buffer_temp_1[15]}},cache_buffer_temp_1[15:0]};
            8'h07 : cache_data_1 = {{32{cache_buffer_temp_1[31]}},cache_buffer_temp_1[31:0]};
            8'h0f : cache_data_1 =                                cache_buffer_temp_1[63:0] ;
            8'h81 : cache_data_1 = {56'b0                        ,cache_buffer_temp_1[ 7:0]};
            8'h83 : cache_data_1 = {48'b0                        ,cache_buffer_temp_1[15:0]};
            8'h87 : cache_data_1 = {32'b0                        ,cache_buffer_temp_1[31:0]};
            default: cache_data_1 = 'b0;
        endcase
    end
    assign rs1_hit[0] =  (i_id_rs1 == i_ex_waddr )&& |i_id_rs1;
    assign rs1_hit[1] =  (i_id_rs1 == i_as0_waddr)&& |i_id_rs1;
    assign rs1_hit[2] =  (i_id_rs1 == i_as1_waddr)&& |i_id_rs1;
    assign rs1_en [0] =  i_ex_wen  && rs1_hit[0] &&((~i_ex_mem2reg)|| addr_en[0]);
    assign rs1_en [1] =  i_as0_wen && rs1_hit[1] &&((~i_as0_memren)|| addr_en[1]);
    assign rs1_en [2] =  i_as1_wen && rs1_hit[2] ;
    assign o_rd1      = rs1_en [0]?(i_ex_mem2reg?cache_data_0:i_ex_wdata ):
                        rs1_en [1]?(i_as0_memren?cache_data_1:i_as0_wdata):
                        rs1_en [2]?i_as1_wdata:
                        i_rd_1;  
    // wire [2:0]rs2_hit;
    // wire [2:0]rs2_en;
    // assign rs2_hit[0] =  (i_id_rs2 == i_ex_waddr ) && |i_id_rs2;
    // assign rs2_hit[1] =  (i_id_rs2 == i_as0_waddr) && |i_id_rs2;
    // assign rs2_hit[2] =  (i_id_rs2 == i_as1_waddr) && |i_id_rs2;
    // assign rs2_en [0] =  i_ex_wen  && rs2_hit[0] &&(~i_ex_mem2reg) ;
    // assign rs2_en [1] =  i_as0_wen && rs2_hit[1] &&(~i_as0_memren);
    // assign rs2_en [2] =  i_as1_wen && rs2_hit[2] ;
    // assign o_rd2      = rs2_en [0]?i_ex_wdata :
    //                     rs2_en [1]?i_as0_wdata:
    //                     rs2_en [2]?i_as1_wdata:
    //                     i_rd_2; 
    wire [2:0]rs2_hit;
    wire [2:0]rs2_en;
    assign rs2_hit[0] =  (i_id_rs2 == i_ex_waddr ) && |i_id_rs2;
    assign rs2_hit[1] =  (i_id_rs2 == i_as0_waddr) && |i_id_rs2;
    assign rs2_hit[2] =  (i_id_rs2 == i_as1_waddr) && |i_id_rs2;
    assign rs2_en [0] =  i_ex_wen  && rs2_hit[0] &&((~i_ex_mem2reg)|| addr_en[0]) ;
    assign rs2_en [1] =  i_as0_wen && rs2_hit[1] &&((~i_as0_memren)|| addr_en[1]);
    assign rs2_en [2] =  i_as1_wen && rs2_hit[2] ;
    assign o_rd2      = rs2_en [0]?(i_ex_mem2reg?cache_data_0:i_ex_wdata ):
                        rs2_en [1]?(i_as0_memren?cache_data_1:i_as0_wdata):
                        rs2_en [2]?i_as1_wdata:
                        i_rd_2; 
    wire [1:0]read_done;
    assign read_done[0] =   (i_as1_memren  && rs1_hit[2])?
                            ((i_ex_mem2reg && rs1_hit[0])?
                            ((i_ex_memraddr == i_as1_memraddr  && i_as0_memren )?1'b1:1'b0):1'b0):1'b0;
    assign read_done[1] =   (i_as1_memren  && rs2_hit[2])?
                            ((i_ex_mem2reg && rs2_hit[0])?
                            ((i_ex_memraddr == i_as1_memraddr  && i_as0_memren )?1'b1:1'b0):1'b0):1'b0;
    assign reg_stop =   ((~read_done[0]) && (rs1_hit[0] && (~rs1_en[0])              )) || 
                        ((~read_done[0]) && (rs1_hit[1] && (~rs1_en[0] && ~rs1_en[1] )))|| 
                        ((~read_done[1]) && (rs2_hit[0] && (~rs2_en[0])              )) ||
                        ((~read_done[1]) && (rs2_hit[1] && (~rs2_en[0] && ~rs2_en[1] )));
endmodule
// module ysyx_050369_reg_sb ( 
//     input        clk,
//     input        rst,
//     input [127:0]i_cache_data,
//     //reg_data
//     input [4:0]  i_id_rs1,
//     input [4:0]  i_id_rs2,
//         //form ex
//     input        i_ex_wen,
//     input [4:0]  i_ex_waddr,
//     input [63:0] i_ex_wdata,
//     input        i_ex_mem2reg,
//     input        i_ex_memwen,
//     input [31:0] i_ex_memraddr,
//     input [7 :0] i_ex_memmask,
//     input        i_as0_wen,
//     input [4:0]  i_as0_waddr,
//     input [63:0] i_as0_wdata,
//     input        i_as0_memren,
//     input [31:0] i_as0_memraddr,
//     input [7 :0] i_as0_memmask,
//     input        i_as0_memwen,
//     input        i_as1_wen,
//     input [4:0]  i_as1_waddr,
//     input [63:0] i_as1_wdata,
//     input        i_as1_memren,
//     input [63:0] i_as1_memrdata,
//     input [31:0] i_as1_memraddr,
//         //form wb
//     input [63:0] i_rd_1,
//     input [63:0] i_rd_2, 
//         //to ex
//     output[63:0] o_rd1,
//     output[63:0] o_rd2,
//     output       reg_stop
// );
//     wire [2:0]rs1_hit;
//     wire [2:0]rs1_en;

//     assign rs1_hit[0] =  (i_id_rs1 == i_ex_waddr )&& |i_id_rs1;
//     assign rs1_hit[1] =  (i_id_rs1 == i_as0_waddr)&& |i_id_rs1;
//     assign rs1_hit[2] =  (i_id_rs1 == i_as1_waddr)&& |i_id_rs1;
//     assign rs1_en [0] =  i_ex_wen  && rs1_hit[0] &&(~i_ex_mem2reg);
//     assign rs1_en [1] =  i_as0_wen && rs1_hit[1] &&(~i_as0_memren);
//     assign rs1_en [2] =  i_as1_wen && rs1_hit[2] ;
//     assign o_rd1      = rs1_en [0]?i_ex_wdata :
//                         rs1_en [1]?i_as0_wdata:
//                         rs1_en [2]?i_as1_wdata:
//                         i_rd_1;  
//     wire [2:0]rs2_hit;
//     wire [2:0]rs2_en;
//     assign rs2_hit[0] =  (i_id_rs2 == i_ex_waddr ) && |i_id_rs2;
//     assign rs2_hit[1] =  (i_id_rs2 == i_as0_waddr) && |i_id_rs2;
//     assign rs2_hit[2] =  (i_id_rs2 == i_as1_waddr) && |i_id_rs2;
//     assign rs2_en [0] =  i_ex_wen  && rs2_hit[0] &&(~i_ex_mem2reg) ;
//     assign rs2_en [1] =  i_as0_wen && rs2_hit[1] &&(~i_as0_memren);
//     assign rs2_en [2] =  i_as1_wen && rs2_hit[2] ;
//     assign o_rd2      = rs2_en [0]?i_ex_wdata :
//                         rs2_en [1]?i_as0_wdata:
//                         rs2_en [2]?i_as1_wdata:
//                         i_rd_2; 
//     // wire [2:0]rs2_hit;
//     // wire [2:0]rs2_en;
//     // assign rs2_hit[0] =  (i_id_rs2 == i_ex_waddr ) && |i_id_rs2;
//     // assign rs2_hit[1] =  (i_id_rs2 == i_as0_waddr) && |i_id_rs2;
//     // assign rs2_hit[2] =  (i_id_rs2 == i_as1_waddr) && |i_id_rs2;
//     // assign rs2_en [0] =  i_ex_wen  && rs2_hit[0] &&((~i_ex_mem2reg)|| addr_en[0]) ;
//     // assign rs2_en [1] =  i_as0_wen && rs2_hit[1] &&((~i_as0_memren)|| addr_en[1]);
//     // assign rs2_en [2] =  i_as1_wen && rs2_hit[2] ;
//     // assign o_rd2      = rs2_en [0]?(i_ex_mem2reg?cache_data_0:i_ex_wdata ):
//     //                     rs2_en [1]?(i_as0_memren?cache_data_1:i_as0_wdata):
//     //                     rs2_en [2]?i_as1_wdata:
//     //                     i_rd_2; 
//     wire [1:0]read_done;
//     assign read_done[0] =   (i_as1_memren  && rs1_hit[2])?
//                             ((i_ex_mem2reg && rs1_hit[0])?
//                             ((i_ex_memraddr == i_as1_memraddr  && i_as0_memren )?1'b1:1'b0):1'b0):1'b0;
//     assign read_done[1] =   (i_as1_memren  && rs2_hit[2])?
//                             ((i_ex_mem2reg && rs2_hit[0])?
//                             ((i_ex_memraddr == i_as1_memraddr  && i_as0_memren )?1'b1:1'b0):1'b0):1'b0;
//     assign reg_stop =   ((~read_done[0]) && (rs1_hit[0] && (~rs1_en[0])              )) || 
//                         ((~read_done[0]) && (rs1_hit[1] && (~rs1_en[0] && ~rs1_en[1] )))|| 
//                         ((~read_done[1]) && (rs2_hit[0] && (~rs2_en[0])              )) ||
//                         ((~read_done[1]) && (rs2_hit[1] && (~rs2_en[0] && ~rs2_en[1] )));
// endmodule
